﻿#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;
// 二进制解码
int decode_binary(Scalar color) {
    double brightness = (color[0] + color[1] + color[2]) / 3.0; // 计算平均亮度
    return brightness > 127 ? 1 : 0; // 亮度阈值判断
}
// 八进制解码
int decode_octal(Scalar color) {
    Mat rgb(1, 1, CV_8UC3, color);
    Mat hsv;
    cvtColor(rgb, hsv, COLOR_BGR2HSV);
    double h = hsv.at<Vec3b>(0, 0)[0]; 
    double s = hsv.at<Vec3b>(0, 0)[1];  
    double v = hsv.at<Vec3b>(0, 0)[2]; 

    if (v < 50) return 0; // 黑色
    if (v > 200 && s < 50) return 1; // 白色
    if (s > 50) {
        if (h < 10 || h > 170) return 2; // 红色
        if (h > 100 && h < 140) return 3; // 蓝色
        if (h > 40 && h < 80) return 4; // 绿色
        if (h > 140 && h < 170) return 5; // 紫色
        if (h > 10 && h < 40) return 6; // 黄色
        if (h > 80 && h < 100) return 7; // 青色
    }
    return 0; 
}
// 接收消息
int receive(bool is_binary = true) {
    VideoCapture cap(0); // 打开摄像头
    if (!cap.isOpened()) {
        cout << "无法打开摄像头" << endl;
        return -1;
    }

    Mat frame;
    cap >> frame; // 读取一帧
    if (frame.empty()) {
        cout << "出现错误" << endl;
        return -1;
    }

    int roi_size = 100;
    Rect roi(frame.cols / 2 - roi_size / 2, frame.rows / 2 - roi_size / 2, roi_size, roi_size);
    Mat region = frame(roi);
    Scalar avg_color = mean(region);

    imshow("Receiver", frame);
    waitKey(1000);

    return is_binary ? decode_binary(avg_color) : decode_octal(avg_color);
}

//下面的部分和sender相似，目的是识别颜色再在屏幕上显示对应颜色的数字
Scalar encode_binary(int msg) {
    if (msg == 0) return Scalar(0, 0, 0);   
    if (msg == 1) return Scalar(255, 255, 255); 
    return Scalar(0, 0, 0); 
}

Scalar encode_octal(int msg) {
    switch (msg) {
    case 0: return Scalar(0, 0, 0);     // 黑色
    case 1: return Scalar(255, 255, 255); // 白色
    case 2: return Scalar(0, 0, 255);   // 红色
    case 3: return Scalar(255, 0, 0);   // 蓝色
    case 4: return Scalar(0, 255, 0);   // 绿色
    case 5: return Scalar(255, 0, 255); // 紫色
    case 6: return Scalar(0, 255, 255); // 黄色
    case 7: return Scalar(255, 255, 0); // 青色
    default: return Scalar(0, 0, 0);    // 默认黑色
    }
}

// 发送消息（显示数字）
void send(int msg, bool is_binary = true) {
    Scalar color = is_binary ? encode_binary(msg) : encode_octal(msg);
    Mat frame(480, 640, CV_8UC3, Scalar(255, 255, 255)); 

    // 将消息转换为字符串
    string text = to_string(msg);
    // 居中显示文本
    int fontFace = FONT_HERSHEY_SIMPLEX;
    double fontScale = 5; // 字体大小
    int thickness = 10;   // 字体粗细
    int baseline = 0;
    Size textSize = getTextSize(text, fontFace, fontScale, thickness, &baseline);
    Point textOrg((frame.cols - textSize.width) / 2, (frame.rows + textSize.height) / 2);
    // 在图像上绘制数字
    putText(frame, text, textOrg, fontFace, fontScale, color, thickness);
    namedWindow("Sender", WINDOW_NORMAL);
    setWindowProperty("Sender", WND_PROP_FULLSCREEN, WINDOW_FULLSCREEN);
    imshow("Sender", frame);
    waitKey(3000); // 显示 3 秒
}

int main() {
    cout << "输入模式 (0=二进制, 1=八进制): ";
    int mode;
    cin >> mode;
    int msg = receive(mode == 0);
    cout << "接收到的消息: " << msg << endl;
    send(msg, mode == 0);
    destroyAllWindows();
    return 0;
}